/*
* Copyright (c) 2025 Huawei Technologies Co., Ltd.
* openUBMC is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
*         http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/

#include <gtest/gtest.h>
#include <test_utilities/test_base.h>
#include "interface/network_port.h"
#include <ncsi_over_mctp/ncsi_over_mctp_mellanox.h>
#include <ncsi/ncsi_mellanox.h>
#include <ncsi/ncsi_protocol.h>
#include <mctp/mctp.h>
#include <mc/engine.h>
#include <mc/common.h>
#include <ctime>
#include <thread>
#include <chrono>
#include <cstring>
#include <vector>
#include <functional>

namespace dev {
void set_mctp_request_handler(std::function<bool(const mc::dict&, const std::vector<uint8_t>&,
                                                 std::string&)> handler);
}

// 字节序转换辅助函数
namespace {
constexpr uint16_t host_to_be16(uint16_t value) {
    return static_cast<uint16_t>(((value & 0x00FFU) << 8U) | ((value & 0xFF00U) >> 8U));
}
}

namespace drivers {
namespace pcie_nic_card {
namespace mellanox {
namespace interface {
namespace test {

class network_port_test_service : public mc::engine::service {
public:
    network_port_test_service(const std::string& name) : mc::engine::service(name) {}
};

// Mock ncsi_over_mctp_mellanox 类
class mock_ncsi_over_mctp_mellanox : public dev::ncsi_over_mctp_mellanox {
public:
    mock_ncsi_over_mctp_mellanox(dev::mctp& mctp_obj) : dev::ncsi_over_mctp_mellanox(mctp_obj) {
    }

    void set_get_mac_addr_result(bool result, uint8_t* mac_addr = nullptr) {
        m_get_mac_addr_result = result;
        if (mac_addr) {
            std::memcpy(m_mac_addr, mac_addr, 6);
        }
    }

    void set_get_default_mac_addr_result(bool result, uint8_t* mac_addr = nullptr) {
        m_get_default_mac_addr_result = result;
        if (mac_addr) {
            std::memcpy(m_default_mac_addr, mac_addr, 6);
        }
    }

    void set_set_lldp_capability_result(bool result) {
        m_set_lldp_capability_result = result;
    }

    void set_get_lldp_capability_result(bool result, uint8_t capability = 0) {
        m_get_lldp_capability_result = result;
        m_lldp_capability            = capability;
    }

    bool set_lldp_capability(uint8_t package_id, uint8_t channel_id, uint8_t lldp_capability) {
        return m_set_lldp_capability_result;
    }

    bool get_lldp_capability(uint8_t package_id, uint8_t channel_id, uint8_t* lldp_capability) {
        if (lldp_capability == nullptr) {
            return false;
        }
        if (!m_get_lldp_capability_result) {
            return false;
        }
        *lldp_capability = m_lldp_capability;
        return true;
    }

    // 获取设置的 MAC 地址，用于构造响应
    bool get_mac_addr_for_response(uint8_t* mac_addr) {
        if (!m_get_mac_addr_result) {
            return false;
        }
        std::memcpy(mac_addr, m_mac_addr, 6);
        return true;
    }

    bool get_default_mac_addr_for_response(uint8_t* mac_addr) {
        if (!m_get_default_mac_addr_result) {
            return false;
        }
        std::memcpy(mac_addr, m_default_mac_addr, 6);
        return true;
    }

    // 获取 LLDP 相关状态，供 handler 使用
    bool get_set_lldp_capability_result() const {
        return m_set_lldp_capability_result;
    }

    bool get_get_lldp_capability_result() const {
        return m_get_lldp_capability_result;
    }

    uint8_t get_lldp_capability() const {
        return m_lldp_capability;
    }

private:
    bool        m_get_mac_addr_result         = false;
    uint8_t     m_mac_addr[6]                 = {};
    bool        m_get_default_mac_addr_result = false;
    uint8_t     m_default_mac_addr[6]        = {};
    bool        m_set_lldp_capability_result = false;
    bool        m_get_lldp_capability_result  = false;
    uint8_t     m_lldp_capability             = 0;
};

// ========================= NetworkPort测试 =========================
class NetworkPortTest : public mc::test::TestWithEngine {
protected:
    static void SetUpTestSuite() {
        TestWithEngine::SetUpTestSuite();
        m_test_service = std::make_unique<network_port_test_service>("bmc.openubmc.test_network_port");
        m_test_service->init();
        m_test_service->start();
    }
    static void TearDownTestSuite() {
        try {
            if (m_test_service) {
                m_test_service->stop();
                m_test_service.reset();
            }
            TestWithEngine::TearDownTestSuite();
        } catch (...) {
        }
    }
    void SetUp() override {
        m_network_port = mc::make_shared<dev::NetworkPort>();
        m_network_port->PortId = 0;

        // 创建 mock ncsi_over_mctp_mellanox
        m_mctp = mc::make_shared<dev::mctp>(nullptr, 0, dev::MCTP_MESSAGE_TYPE_NCSI, "");
        m_mock_ncsi = std::make_shared<mock_ncsi_over_mctp_mellanox>(*m_mctp);

        // 设置 MCTP 请求处理器，用于拦截 MAC 地址相关请求
        // 使用 weak_ptr 来避免悬空指针问题
        std::weak_ptr<mock_ncsi_over_mctp_mellanox> weak_mock_ncsi = m_mock_ncsi;
        dev::set_mctp_request_handler([weak_mock_ncsi](const mc::dict& ctx,
                                                       const std::vector<uint8_t>& data,
                                                       std::string& rsp) {
            // 检查是否是 OEM 命令
            if (!ctx.contains("PacketType") ||
                ctx.at("PacketType").as<int64_t>() != OEM_COMMAND) {
                return false;
            }

            // OEM 命令需要检查数据长度
            if (data.size() < 8) {
                return false;
            }

            // 从 weak_ptr 获取 shared_ptr，如果对象已被释放则返回 false
            auto mock_ncsi = weak_mock_ncsi.lock();
            if (!mock_ncsi) {
                return false;
            }

            // 解析命令：MELLANOX_COMMON_DATA 格式为 {0x00, 0x00, 0x81, 0x19, REV_ID, cmd_id, parameter, optional_data}
            uint8_t cmd_id    = data[5];
            uint8_t parameter = data[6];

            // 处理 GET_PF_MAC 命令
            if (cmd_id == OEM_MLNX_GET_PF_MAC_CMD && parameter == OEM_MLNX_GET_PF_MAC_PARA) {
                uint8_t mac_addr[6] = {};
                if (!mock_ncsi->get_mac_addr_for_response(mac_addr)) {
                    return false;
                }

                oem_mlnx_mac_addr_rsp_t rsp_data = {};
                rsp_data.public_rsp_header.response_code   = host_to_be16(0);
                rsp_data.public_rsp_header.reason_code     = host_to_be16(0);
                rsp_data.public_rsp_header.manufacturer_id = MELLANOX_MANUFACTURE_ID_REP;
                rsp_data.public_rsp_header.reserved        = 0;
                rsp_data.public_rsp_header.command_id      = OEM_MLNX_GET_PF_MAC_CMD;
                rsp_data.public_rsp_header.parameter       = OEM_MLNX_GET_PF_MAC_PARA;
                rsp_data.public_rsp_header.optional_data    = 0;
                std::memcpy(rsp_data.mac_addr, mac_addr, 6);
                rsp_data.reserved[0] = 0;
                rsp_data.reserved[1] = 0;
                rsp_data.check_sum   = 0;

                rsp = std::string(reinterpret_cast<const char*>(&rsp_data), OEM_MLNX_MAC_ADDR_RSP_LEN);
                return true;
            }

            // 处理 GET_PORT_ID 命令（用于获取默认 MAC 地址）
            if (cmd_id == OEM_MLNX_GET_PORT_ID_CMD && parameter == OEM_MLNX_GET_PORT_ID_PARA) {
                uint8_t mac_addr[6] = {};
                if (!mock_ncsi->get_default_mac_addr_for_response(mac_addr)) {
                    return false;
                }

                oem_mlnx_port_id_rsp_t rsp_data = {};
                rsp_data.public_rsp_header.response_code   = host_to_be16(0);
                rsp_data.public_rsp_header.reason_code     = host_to_be16(0);
                rsp_data.public_rsp_header.manufacturer_id = MELLANOX_MANUFACTURE_ID_REP;
                rsp_data.public_rsp_header.reserved        = 0;
                rsp_data.public_rsp_header.command_id      = OEM_MLNX_GET_PORT_ID_CMD;
                rsp_data.public_rsp_header.parameter       = OEM_MLNX_GET_PORT_ID_PARA;
                rsp_data.public_rsp_header.optional_data    = 0;
                std::memcpy(rsp_data.mac_addr, mac_addr, 6);
                rsp_data.reserved[0] = 0;
                rsp_data.reserved[1] = 0;
                std::memset(rsp_data.port_guid, 0, 8);
                rsp_data.check_sum = 0;

                rsp = std::string(reinterpret_cast<const char*>(&rsp_data), OEM_MLNX_PORT_ID_RSP_LEN);
                return true;
            }

            // 处理 SET_LLDP 命令
            if (cmd_id == OEM_MLNX_SET_LLDP_CMD && parameter == OEM_MLNX_SET_LLDP_PARA) {
                // 检查 mock 结果
                if (!mock_ncsi->get_set_lldp_capability_result()) {
                    return false;
                }

                // 使用固定大小的字符数组构造响应，避免动态分配和内存问题
                char rsp_buffer[OEM_MLNX_LLDP_RSP_LEN] = {0};
                
                // 填充公共响应头 (12字节)
                uint16_t response_code = host_to_be16(0);
                uint16_t reason_code = host_to_be16(0);
                std::memcpy(&rsp_buffer[0], &response_code, 2);
                std::memcpy(&rsp_buffer[2], &reason_code, 2);
                uint32_t manufacturer_id = MELLANOX_MANUFACTURE_ID_REP;
                std::memcpy(&rsp_buffer[4], &manufacturer_id, 4);
                rsp_buffer[8] = 0; // reserved
                rsp_buffer[9] = OEM_MLNX_SET_LLDP_CMD;
                rsp_buffer[10] = OEM_MLNX_SET_LLDP_PARA;
                rsp_buffer[11] = 0; // optional_data
                
                // reserved[3] (3字节)
                rsp_buffer[12] = 0;
                rsp_buffer[13] = 0;
                rsp_buffer[14] = 0;
                
                // 位域字节（第15个字节）：根据请求数据设置
                if (data.size() >= 12) {
                    uint8_t lldp_data = data[11];
                    rsp_buffer[15] = (lldp_data & 0x10) ? 1 : 0;
                } else {
                    rsp_buffer[15] = 1; // 默认使能
                }

                rsp = std::string(rsp_buffer, OEM_MLNX_LLDP_RSP_LEN);
                return true;
            }

            // 处理 GET_LLDP 命令
            if (cmd_id == OEM_MLNX_GET_LLDP_CMD && parameter == OEM_MLNX_GET_LLDP_PARA) {
                // 检查 mock 结果
                if (!mock_ncsi->get_get_lldp_capability_result()) {
                    return false;
                }

                // 使用固定大小的字符数组构造响应，避免动态分配和内存问题
                char rsp_buffer[OEM_MLNX_LLDP_RSP_LEN] = {0};
                
                // 填充公共响应头 (12字节)
                uint16_t response_code = host_to_be16(0);
                uint16_t reason_code = host_to_be16(0);
                std::memcpy(&rsp_buffer[0], &response_code, 2);
                std::memcpy(&rsp_buffer[2], &reason_code, 2);
                uint32_t manufacturer_id = MELLANOX_MANUFACTURE_ID_REP;
                std::memcpy(&rsp_buffer[4], &manufacturer_id, 4);
                rsp_buffer[8] = 0; // reserved
                rsp_buffer[9] = OEM_MLNX_GET_LLDP_CMD;
                rsp_buffer[10] = OEM_MLNX_GET_LLDP_PARA;
                rsp_buffer[11] = 0; // optional_data
                
                // reserved[3] (3字节)
                rsp_buffer[12] = 0;
                rsp_buffer[13] = 0;
                rsp_buffer[14] = 0;
                
                // 位域字节（第15个字节）：根据 mock 设置的 capability 值
                rsp_buffer[15] = mock_ncsi->get_lldp_capability() & 0x03;

                rsp = std::string(rsp_buffer, OEM_MLNX_LLDP_RSP_LEN);
                return true;
            }

            return false;
        });
    }
    void TearDown() override {
        try {
            // 先停止任务，等待异步操作完成
            if (m_network_port) {
                m_network_port->stop_ncsi_update_task();
                // 等待足够长时间，确保定时器完全停止，避免在对象析构时定时器仍在运行
                std::this_thread::sleep_for(std::chrono::milliseconds(100));
            }
            
            // 清除 MCTP 请求处理器，避免 handler 在对象释放后仍被调用
            dev::set_mctp_request_handler(nullptr);
            
            // 等待一段时间，确保所有异步操作完成
            std::this_thread::sleep_for(std::chrono::milliseconds(50));
            
            // 释放资源
            if (m_network_port) {
                m_network_port.reset();
            }
            m_mock_ncsi.reset();
            m_mctp.reset();
        } catch (...) {
            // 异常情况下也要清理资源
            dev::set_mctp_request_handler(nullptr);
            if (m_network_port) {
                m_network_port.reset();
            }
            m_mock_ncsi.reset();
            m_mctp.reset();
        }
    }

    static std::unique_ptr<network_port_test_service> m_test_service;
    mc::shared_ptr<dev::NetworkPort>                  m_network_port;
    mc::shared_ptr<dev::mctp>                         m_mctp;
    std::shared_ptr<mock_ncsi_over_mctp_mellanox>     m_mock_ncsi;
};
std::unique_ptr<network_port_test_service> NetworkPortTest::m_test_service;

// ========================= 基本功能测试 =========================

TEST_F(NetworkPortTest, Constructor) {
    dev::NetworkPort network_port;
    EXPECT_TRUE(true);
}

TEST_F(NetworkPortTest, Destructor_CleansUpResources) {
    auto network_port = mc::make_shared<dev::NetworkPort>();

    // 启动任务后析构
    mc::milliseconds interval(1000);
    uint8_t          package_id = 0;
    network_port->start_ncsi_update_task_mellanox(m_mock_ncsi, interval, package_id);
    std::this_thread::sleep_for(std::chrono::milliseconds(50));

    network_port->stop_ncsi_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(10));
    network_port.reset();

    EXPECT_TRUE(network_port == nullptr);
}

// ========================= update_mac_addr_by_ncsi 测试 =========================

TEST_F(NetworkPortTest, UpdateMacAddrByNcsi_Success) {
    uint8_t mac_addr[6] = {0x00, 0x1B, 0x21, 0x85, 0x6F, 0x6B};
    m_mock_ncsi->set_get_mac_addr_result(true, mac_addr);

    // 需要先设置 ncsi_over_mctp_mellanox
    mc::milliseconds interval(1000);
    uint8_t          package_id = 0;
    m_network_port->start_ncsi_update_task_mellanox(m_mock_ncsi, interval, package_id);
    std::this_thread::sleep_for(std::chrono::milliseconds(50));

    bool result = m_network_port->update_mac_addr_by_ncsi();
    EXPECT_TRUE(result);
    std::string mac_addr_str = m_network_port->MACAddress.get_value().as<std::string>();
    EXPECT_TRUE(mac_addr_str.find("00:1B:21:85:6F:6B") != std::string::npos ||
                mac_addr_str == "00:1B:21:85:6F:6B");
    
    // 停止定时器，确保资源正确清理
    m_network_port->stop_ncsi_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

TEST_F(NetworkPortTest, UpdateMacAddrByNcsi_GetMacAddrFailed) {
    m_mock_ncsi->set_get_mac_addr_result(false);

    mc::milliseconds interval(1000);
    uint8_t          package_id = 0;
    m_network_port->start_ncsi_update_task_mellanox(m_mock_ncsi, interval, package_id);
    std::this_thread::sleep_for(std::chrono::milliseconds(50));

    bool result = m_network_port->update_mac_addr_by_ncsi();
    EXPECT_FALSE(result);
    
    // 停止定时器，确保资源正确清理
    m_network_port->stop_ncsi_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

TEST_F(NetworkPortTest, UpdateMacAddrByNcsi_WithoutNcsiInitialized) {
    // 不启动任务，直接调用 update_mac_addr_by_ncsi
    bool result = m_network_port->update_mac_addr_by_ncsi();
    // 由于 m_ncsi_over_mctp_mellanox 为 nullptr，应该会失败
    EXPECT_FALSE(result);
}

// ========================= update_default_mac_addr_by_ncsi 测试 =========================

TEST_F(NetworkPortTest, UpdateDefaultMacAddrByNcsi_Success) {
    uint8_t mac_addr[6] = {0x00, 0x1B, 0x21, 0x85, 0x6F, 0x6C};
    m_mock_ncsi->set_get_default_mac_addr_result(true, mac_addr);

    mc::milliseconds interval(1000);
    uint8_t          package_id = 0;
    m_network_port->start_ncsi_update_task_mellanox(m_mock_ncsi, interval, package_id);
    std::this_thread::sleep_for(std::chrono::milliseconds(50));

    bool result = m_network_port->update_default_mac_addr_by_ncsi();
    EXPECT_TRUE(result);
    std::string mac_addr_str = m_network_port->PermanentMACAddress.get_value().as<std::string>();
    EXPECT_TRUE(mac_addr_str.find("00:1B:21:85:6F:6C") != std::string::npos ||
                mac_addr_str == "00:1B:21:85:6F:6C");
    
    // 停止定时器，确保资源正确清理
    m_network_port->stop_ncsi_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

TEST_F(NetworkPortTest, UpdateDefaultMacAddrByNcsi_UpdatesMacAddressIfEmpty) {
    // 设置 MACAddress 为空或 "N/A"
    m_network_port->MACAddress.set_value("00:00:00:00:00:00");

    uint8_t mac_addr[6] = {0x00, 0x1B, 0x21, 0x85, 0x6F, 0x6D};
    m_mock_ncsi->set_get_default_mac_addr_result(true, mac_addr);

    mc::milliseconds interval(1000);
    uint8_t          package_id = 0;
    m_network_port->start_ncsi_update_task_mellanox(m_mock_ncsi, interval, package_id);
    std::this_thread::sleep_for(std::chrono::milliseconds(50));

    bool result = m_network_port->update_default_mac_addr_by_ncsi();
    EXPECT_TRUE(result);
    // MACAddress 应该被更新
    std::string mac_addr_str = m_network_port->MACAddress.get_value().as<std::string>();
    EXPECT_TRUE(mac_addr_str.find("00:1B:21:85:6F:6D") != std::string::npos ||
                mac_addr_str == "00:1B:21:85:6F:6D");
    
    // 停止定时器，确保资源正确清理
    m_network_port->stop_ncsi_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

// ========================= set_lldp_capability_by_ncsi 测试 =========================

TEST_F(NetworkPortTest, SetLldpCapabilityByNcsi_Success) {
    m_mock_ncsi->set_set_lldp_capability_result(true);

    mc::milliseconds interval(1000);
    uint8_t          package_id = 0;
    m_network_port->start_ncsi_update_task_mellanox(m_mock_ncsi, interval, package_id);
    std::this_thread::sleep_for(std::chrono::milliseconds(50));

    bool result = m_network_port->set_lldp_capability_by_ncsi(1);
    EXPECT_TRUE(result);
    
    // 停止定时器，确保资源正确清理
    m_network_port->stop_ncsi_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

TEST_F(NetworkPortTest, SetLldpCapabilityByNcsi_Failed) {
    m_mock_ncsi->set_set_lldp_capability_result(false);

    mc::milliseconds interval(1000);
    uint8_t          package_id = 0;
    m_network_port->start_ncsi_update_task_mellanox(m_mock_ncsi, interval, package_id);
    std::this_thread::sleep_for(std::chrono::milliseconds(50));

    bool result = m_network_port->set_lldp_capability_by_ncsi(1);
    EXPECT_FALSE(result);
    
    // 停止定时器，确保资源正确清理
    m_network_port->stop_ncsi_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

// ========================= get_lldp_capability_by_ncsi 测试 =========================

TEST_F(NetworkPortTest, GetLldpCapabilityByNcsi_AlreadyEnabled) {
    // 如果 LLDPEnabled 已经为 true，应该直接返回 true
    m_network_port->LLDPEnabled.set_value(true);

    // 需要初始化 NCSI，即使不会使用它
    mc::milliseconds interval(1000);
    uint8_t          package_id = 0;
    m_network_port->start_ncsi_update_task_mellanox(m_mock_ncsi, interval, package_id);
    std::this_thread::sleep_for(std::chrono::milliseconds(50));

    bool result = m_network_port->get_lldp_capability_by_ncsi();
    EXPECT_TRUE(result);
    
    // 停止定时器，确保资源正确清理，避免在 TearDown 中重复停止导致问题
    m_network_port->stop_ncsi_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

// ========================= SendNcsiTestPacket 测试 =========================

TEST_F(NetworkPortTest, SendNcsiTestPacket_Success) {
    // 针对 SendNcsiTestPacket 场景，单独设置 MCTP handler 来模拟标准 NCSI 测试包行为
    dev::set_mctp_request_handler([](const mc::dict& ctx, const std::vector<uint8_t>& data,
                                     std::string& rsp) {
        // PacketType 即为 NCSI 命令码，这里期望为 0x01
        EXPECT_EQ(ctx.at("PacketType").as<int64_t>(), 0x01);
        // 请求数据应与传入的 req_data 一致
        EXPECT_EQ(data, std::vector<uint8_t>({'t', 'e', 's', 't', '_', 'd', 'a', 't', 'a'}));
        // 模拟请求成功且响应非空
        rsp = "ok";
        return true;
    });

    mc::milliseconds interval(1000);
    uint8_t          package_id = 0;
    m_network_port->start_ncsi_update_task_mellanox(m_mock_ncsi, interval, package_id);
    std::this_thread::sleep_for(std::chrono::milliseconds(50));

    uint8_t      cmd_code = 0x01;
    std::string  req_data = "test_data";
    bool         result   = m_network_port->SendNcsiTestPacket(cmd_code, req_data);
    EXPECT_TRUE(result);
}

TEST_F(NetworkPortTest, SendNcsiTestPacket_WithoutNcsiInitialized) {
    // 不启动任务，直接调用 SendNcsiTestPacket，此时 m_ncsi_over_mctp_mellanox 为 nullptr
    uint8_t     cmd_code = 0x01;
    std::string req_data = "test_data";
    bool        result   = m_network_port->SendNcsiTestPacket(cmd_code, req_data);
    EXPECT_FALSE(result);
}

TEST_F(NetworkPortTest, SendNcsiTestPacket_Failed) {
    // 模拟 request 失败的场景：handler 返回 false
    dev::set_mctp_request_handler([](const mc::dict& ctx, const std::vector<uint8_t>& data,
                                     std::string& rsp) {
        EXPECT_EQ(ctx.at("PacketType").as<int64_t>(), 0x01);
        EXPECT_EQ(data, std::vector<uint8_t>({'t', 'e', 's', 't', '_', 'd', 'a', 't', 'a'}));
        rsp.clear();
        return false;
    });

    mc::milliseconds interval(1000);
    uint8_t          package_id = 0;
    m_network_port->start_ncsi_update_task_mellanox(m_mock_ncsi, interval, package_id);
    std::this_thread::sleep_for(std::chrono::milliseconds(50));

    uint8_t     cmd_code = 0x01;
    std::string req_data = "test_data";
    bool        result   = m_network_port->SendNcsiTestPacket(cmd_code, req_data);
    EXPECT_FALSE(result);
    
    // 停止定时器，确保资源正确清理
    m_network_port->stop_ncsi_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

// ========================= SetLLDPTxEnable 测试 =========================

TEST_F(NetworkPortTest, SetLLDPTxEnable_Enable) {
    m_mock_ncsi->set_set_lldp_capability_result(true);

    mc::milliseconds interval(1000);
    uint8_t          package_id = 0;
    m_network_port->start_ncsi_update_task_mellanox(m_mock_ncsi, interval, package_id);
    std::this_thread::sleep_for(std::chrono::milliseconds(50));

    bool result = m_network_port->SetLLDPTxEnable(true);
    EXPECT_TRUE(result);
    EXPECT_TRUE(m_network_port->LLDPEnabled.get_value().as<bool>());
    
    // 停止定时器，确保资源正确清理
    m_network_port->stop_ncsi_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

TEST_F(NetworkPortTest, SetLLDPTxEnable_Disable) {
    m_mock_ncsi->set_set_lldp_capability_result(true);

    mc::milliseconds interval(1000);
    uint8_t          package_id = 0;
    m_network_port->start_ncsi_update_task_mellanox(m_mock_ncsi, interval, package_id);
    std::this_thread::sleep_for(std::chrono::milliseconds(50));

    bool result = m_network_port->SetLLDPTxEnable(false);
    EXPECT_TRUE(result);
    EXPECT_FALSE(m_network_port->LLDPEnabled.get_value().as<bool>());
    
    // 停止定时器，确保资源正确清理
    m_network_port->stop_ncsi_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

TEST_F(NetworkPortTest, SetLLDPTxEnable_WithoutNcsiInitialized) {
    // 不启动任务，直接调用 SetLLDPTxEnable
    bool result = m_network_port->SetLLDPTxEnable(true);
    EXPECT_FALSE(result);
}

TEST_F(NetworkPortTest, SetLLDPTxEnable_Failed) {
    m_mock_ncsi->set_set_lldp_capability_result(false);

    mc::milliseconds interval(1000);
    uint8_t          package_id = 0;
    m_network_port->start_ncsi_update_task_mellanox(m_mock_ncsi, interval, package_id);
    std::this_thread::sleep_for(std::chrono::milliseconds(50));

    bool result = m_network_port->SetLLDPTxEnable(true);
    EXPECT_FALSE(result);
    
    // 停止定时器，确保资源正确清理
    m_network_port->stop_ncsi_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

// ========================= start_ncsi_update_task_mellanox 测试 =========================

TEST_F(NetworkPortTest, StartNcsiUpdateTask_Success) {
    mc::milliseconds interval(1000);
    uint8_t          package_id = 0;

    m_network_port->start_ncsi_update_task_mellanox(m_mock_ncsi, interval, package_id);
    std::this_thread::sleep_for(std::chrono::milliseconds(50));

    // 验证任务已启动，可以通过停止来验证
    m_network_port->stop_ncsi_update_task();
    EXPECT_TRUE(true);
}

// ========================= stop_ncsi_update_task 测试 =========================

TEST_F(NetworkPortTest, StopNcsiUpdateTask_WithoutStart) {
    // 未启动时停止应该能正常处理
    m_network_port->stop_ncsi_update_task();
    EXPECT_TRUE(true);
}

TEST_F(NetworkPortTest, StopNcsiUpdateTask_AfterStart) {
    mc::milliseconds interval(1000);
    uint8_t          package_id = 0;

    m_network_port->start_ncsi_update_task_mellanox(m_mock_ncsi, interval, package_id);
    std::this_thread::sleep_for(std::chrono::milliseconds(50));

    m_network_port->stop_ncsi_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(10));
    EXPECT_TRUE(true);
}

// ========================= 定时器回调测试 =========================

TEST_F(NetworkPortTest, TimerCallback_UpdatesMacAddress) {
    uint8_t mac_addr[6] = {0x00, 0x1B, 0x21, 0x85, 0x6F, 0x6E};
    m_mock_ncsi->set_get_mac_addr_result(true, mac_addr);

    mc::milliseconds interval(100);
    uint8_t          package_id = 0;
    m_network_port->start_ncsi_update_task_mellanox(m_mock_ncsi, interval, package_id);

    // 等待定时器触发
    std::this_thread::sleep_for(std::chrono::milliseconds(200));

    // 验证 MAC 地址是否被更新（由于定时器回调会调用 update_mac_addr_by_ncsi）
    // 注意：由于是异步操作，这里主要验证不会崩溃
    m_network_port->stop_ncsi_update_task();
    std::this_thread::sleep_for(std::chrono::milliseconds(10));
    EXPECT_TRUE(true);
}

// ========================= 多实例测试 =========================

TEST_F(NetworkPortTest, MultiInstance) {
    std::vector<mc::shared_ptr<dev::NetworkPort>> network_ports;
    for (int i = 0; i < 3; i++) {
        std::string object_name =
            "network_port_" + std::to_string(i) + "_" + std::to_string(std::time(nullptr)) + "_" +
            std::to_string(i * 1000);
        std::string position = std::to_string(i + 11000);

        auto network_port = mc::make_shared<dev::NetworkPort>();
        network_port->PortId = i;

        mc::milliseconds interval(1000);
        uint8_t          package_id = i;
        network_port->start_ncsi_update_task_mellanox(m_mock_ncsi, interval, package_id);
        network_ports.push_back(network_port);
    }

    std::this_thread::sleep_for(std::chrono::milliseconds(50));

    for (auto& network_port : network_ports) {
        if (network_port && m_test_service) {
            try {
                network_port->stop_ncsi_update_task();
                std::this_thread::sleep_for(std::chrono::milliseconds(10));
            } catch (...) {
            }
        }
    }
    network_ports.clear();
    std::this_thread::sleep_for(std::chrono::milliseconds(50));
    EXPECT_TRUE(true);
}

} // namespace test
} // namespace interface
} // namespace mellanox
} // namespace pcie_nic_card
} // namespace drivers

